/* Schema dependencies */

var Disease = require('../schema/DiseaseSchema').DiseaseSchema;
var Round = require('../schema/RoundSchema').RoundSchema;
var Game = require('../schema/GameSchema').GameSchema;

/**
 * Creates a new Round object in the database and returns JSON success/error.
 * A separate function is created to not have to repeat myself when doing the
 * random Gene picking trick with MongoDB.
 *
 * @param req  {HTTP Request}  : HTTP POST request passed from the route
 * @param res  {HTTP Response} : Waiting HTTP response passed from the route
 * @param gene {Gene Model}    : Random gene picked from Gene.findOne()
 *
 * @response {JSON object}     : JSON object representing success or error
 **/

var createNewRound = function(req, res, disease) {
    /*
     * Certain parts of the game are preset when generating a new one,
     * such as the starting number of points and the starting round.
     */

    var id = Math.floor(Math.random() * 9000000) + 1000000, 
        newRound = new Round(
        {
            id            : req.params.game + "_" + id,
            points        : 0,
            players : {
                hinter  : req.body.players.hinter,
                guesser : req.body.players.guesser
            },
            guess_target  : disease.id,
            actions : {
                hints   : [],
                guesses : [] 
            },
            turn     : req.body.turn,
            complete : false
        }
    );

    Game.findOne({id: req.params.game}, function(err, game) {
        game.rounds.push(newRound);

        game.save(function(err) {
            if (err) {
                console.log(err);
            } else {
                var returnBody = {
                    success : true,
                    id      : newRound.id,
                    code    : 100,
                    message : "Round successfully added to target Game."
                };
                res.json(returnBody);
            }
        });
    });
};

/**
 * Finds all Rounds that satisfy the given parameters.
 * See API documentation: GET /games/[game_id]/rounds/
 *
 * @param req  {HTTP Request}  : HTTP GET request passed from the route
 * @param res  {HTTP Response} : Waiting HTTP response passed from the route
 *
 * @response {JSON Object}     : JSON array of Round objects
 **/

exports.index = function(req, res) {
    var gameId  = req.params.game,
        query   = Game.findOne({id: gameId}).exclude('_id', 'rounds._id', 
                    'actions.hints._id', 'actions.guesses._id');

    // Limit query by range
    if (req.query.range) {
        query.limit(req.query.range);
    }

    // Execute the query
    query.exec(function(err, game) {
        if (err) { 
            console.log(err);
        } else {
            res.json(game.rounds);
        }
    });
};

/**
 * Creates a Round object using the parameters found in the request body.
 * See API documentation: POST /games/[game_id]/rounds/
 *
 * @param req  {HTTP Request}  : HTTP POST request passed from the route
 * @param res  {HTTP Response} : Waiting HTTP response passed from the route
 *
 * @response {JSON Object}     : JSON object representing success or error
 **/


exports.create = function(req, res) {

    /**
     * "Proper" method of selecting a random object in a MongoDB collection
     * Detailed at: http://cookbook.mongodb.org/patterns/random-attribute/
     */

    var rand = Math.floor(Math.random() * 10000);
    console.log(rand);
    Disease.where('id').gte(rand).findOne(function(err, disease) {
        if (!disease) {
            Disease.where('id').lte(rand).findOne(function(err, nextDisease) {
                createNewRound(req, res, nextDisease);
            });
        } else {
            createNewRound(req, res, disease);
        }
    });
};

/**
 * Finds a single Round object with the given round and game IDs.
 * See API documentation: GET /games/[game_id]/rounds/[round_id]
 *
 * @param req  {HTTP Request}  : HTTP GET request passed from the route
 * @param res  {HTTP Response} : Waiting HTTP response passed from the route
 *
 * @response {JSON Object}     : JSON representation of desired Round object
 **/

exports.show = function(req, res) {
    var gameId  = req.params.game,
        roundId = gameId + '_' + req.params.round,
        query = Game.findOne()
            .where('id').equals(gameId)
            .exclude('_id', 'actions.hints._id', 'actions.guesses._id');

    query.exec(function(err, game) {
        // TODO: JSON error messages
        if (err) { 
            console.log(err);
        } else {
            var i, rounds = game.rounds;
            for (i = 0; i < game.rounds.length; i++) {
                if (game.rounds[i].id == roundId) {
                    break;
                }
            }
            res.json(game.rounds[i]);
        }
    });
};

/**
 * Updates a single Round object with the given game and round IDs.
 * Accepts partial representations of the Round object.
 * See API documentation: PUT /games/[game_id]/rounds/[round_id]
 *
 * @param req  {HTTP Request}  : HTTP PUT request passed from the route
 * @param res  {HTTP Response} : Waiting HTTP response passed from the route
 *
 * @response {JSON Object}     : JSON object representing success or error.
 **/

exports.update = function(req, res) {
    var gameId = req.params.game;
    var roundId = gameId + "_" + req.params.round;

    Game.findOne({id: gameId}, function(err, game) {
        var i;
        var rounds = game.rounds;
        for (i = 0; i < rounds.length; i++) {
            if (rounds[i].id == roundId) {
                if (req.body.points) {
                    game.rounds[i].points = req.body.points;
                }
                if (req.body.complete) {
                    game.rounds[i].complete = req.body.complete;
                }
                if (req.body.turn) {
                    game.rounds[i].turn = req.body.turn;
                }
                game.save(function(err) {
                    if (err) {
                        console.log(err);
                    } else {
                        var returnBody = {
                            success : true,
                            code    : 200,
                            message : "Round successfully updated in database."
                        };
                        res.json(returnBody);
                    }
                });
            }
        }
    }); 
};

/**
 * Deletes a single Round object with the given game and round IDs.
 * See API documentation: DELETE /games/[game_id]/rounds/[round_id]
 *
 * @param req  {HTTP Request}  : HTTP DELETE request passed from the route
 * @param res  {HTTP Response} : Waiting HTTP response passed from the route
 *
 * @response {JSON Object}     : JSON object representing success or error.
 **/

exports.destroy = function(req, res) {
    var id = req.params.game + "_" + req.params.round;
    Game.findOne({id: req.params.game}, function(err, game) {
        var i;
        var rounds = game.rounds;
        for (i = 0; i < rounds.length; i++) {
            if (rounds[i].id == id) {
                game.rounds[i].remove();
                game.save(function(err) {
                    if (err) {
                        console.log(err);
                    } else {
                        var returnBody = {
                            success : true,
                            code    : 300,
                            message : "Round successfully deleted from the database."
                        };
                        res.json(returnBody);
                    }
                });
                break;
            }
        }
    });
};
